﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Configuration;
using Icst.Leaflike.Cache;
using Icst.Leaflike.Logging;

namespace Icst.Leaflike.Data
{
    public class DataContext<TDerived> : IDisposable where TDerived:new()
    {
        public static TDerived Instance { get; private set; }
        static DataContext() { Instance = new TDerived(); }

        private leaflikeDataContext _context;
        protected leaflikeDataContext Context
        {
            get
            {
                lock (this)
                {
                    if (_context == null)
                    {
                        string conn = ConfigurationManager.ConnectionStrings["default"].ConnectionString;
                        _context = new leaflikeDataContext(conn);
                    }
                }
                return _context;
            }
        }

        public ICachePolicy CachePolicy { get; private set; }

        protected DataContext()
        {
            CachePolicy = new MemcachedCachePolicy();
        }

        public virtual void Refresh() 
        {
            try
            {
                Logger.Info("REFRESH DATA");

                Logger.Info("REFRESH Context.Refresh");
                Context.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues);

                Logger.Info("REFRESH Context.ClearCache");
                const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
                var method = Context.GetType().GetMethod("ClearCache", FLAGS);
                method.Invoke(Context, null);
            }
            catch(Exception e) 
            {
                Logger.Error("FAILED TO REFRESH. " + e.Message);
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        protected virtual void Dispose(bool disposing)
        {
            if (_context != null)
                _context.Dispose();
        }
    }
}
